package cn.cangnova.controller.api

import cn.cangnova.UserSession
import cn.cangnova.getJwtConfig
import cn.cangnova.model.ApiResponse
import cn.cangnova.model.BulkDeleteRequest
import cn.cangnova.model.CreateUserRequest
import cn.cangnova.model.LoginRequest
import cn.cangnova.model.RefreshTokenRequest
import cn.cangnova.model.UpdateUserRequest
import cn.cangnova.repository.factory.AdminUserRepositoryFactory
import io.ktor.http.*
import io.ktor.server.auth.*
import io.ktor.server.auth.jwt.*
import io.ktor.server.request.*
import io.ktor.server.response.respond
import io.ktor.server.routing.*
import io.ktor.server.sessions.*
import io.ktor.server.sessions.clear
import kotlinx.serialization.Serializable
import kotlinx.serialization.json.JsonArray
import kotlinx.serialization.json.JsonElement
import kotlinx.serialization.json.buildJsonObject
import kotlinx.serialization.json.put
import mu.KotlinLogging

private val logger = KotlinLogging.logger {}

// 使用工厂获取仓库实例
private val repository = AdminUserRepositoryFactory.getRepository()

/**
 * 令牌刷新响应
 */
@Serializable
data class TokenRefreshResponse(
    val success: Boolean,
    val token: String? = null,
    val refreshToken: String? = null,
    val expiresIn: Int? = null,
    val message: String? = null
)

/**
 * 批量更新状态请求
 */
@Serializable
data class BulkUpdateStatusRequest(
    val ids: List<String>,
    val status: String
)

/**
 * 用户认证 API 路由
 */
fun Route.authApiRoutes() {
    // 登录API
    post("/login") {
        try {
            val request = call.receive<LoginRequest>()

            val user = repository.validateCredentials(request.username, request.password)

            if (user != null) {
                // 更新最后登录时间
                repository.updateLastLoginTime(user.username)

                // 获取JWT配置
                val jwtConfig = call.application.getJwtConfig()

                // 生成JWT令牌
                val token = jwtConfig.generateToken(user.username, user.role)
                val refreshToken = jwtConfig.generateRefreshToken(user.username)

                // 设置会话（向后兼容）
                call.sessions.set(UserSession(user.username))

                // 创建响应对象
                call.respond(
                    HttpStatusCode.OK,
                    ApiResponse(
                        success = true,
                        data = buildJsonObject {
                            put("user", buildJsonObject {
                                put("username", user.username)
                                put("displayName", user.displayName)
                                put("email", user.email)
                                put("role", user.role)
                                put("createdAt", user.createdAt)
                                put("lastLogin", user.lastLoginAt)
                            })
                            put("token", token)
                            put("refreshToken", refreshToken)
                            put("expiresIn", 3600)
                        },
                        message = "登录成功"
                    )
                )
            } else {
                call.respond(
                    HttpStatusCode.OK,
                    ApiResponse(
                        success = false,
                        data = null,
                        message = "用户名或密码错误"
                    )
                )
            }
        } catch (e: Exception) {
            logger.error(e) { "登录失败: ${e.message}" }
            call.respond(
                HttpStatusCode.InternalServerError,
                ApiResponse(
                    success = false,
                    data = null,
                    message = "登录失败: ${e.message}"
                )
            )
        }
    }

    // 登出API
    post("/logout") {
        try {
            call.sessions.clear<UserSession>()
            call.respond(
                HttpStatusCode.OK,
                ApiResponse(
                    success = true,
                    data = null,
                    message = "已成功登出"
                )
            )
        } catch (e: Exception) {
            logger.error(e) { "登出失败: ${e.message}" }
            call.respond(
                HttpStatusCode.InternalServerError,
                ApiResponse(
                    success = false,
                    data = null,
                    message = "登出失败: ${e.message}"
                )
            )
        }
    }

    // 刷新令牌API
    post("/refresh") {
        try {
            val request = call.receive<RefreshTokenRequest>()
            val refreshToken = request.refreshToken

            // 验证刷新令牌
            val jwtConfig = call.application.getJwtConfig()

            try {
                val jwt = jwtConfig.verifier.verify(refreshToken)
                val username = jwt.getClaim("username").asString()

                // 检查用户是否存在
                val user = repository.findByUsername(username)

                if (user != null) {
                    // 生成新的访问令牌
                    val newToken = jwtConfig.generateToken(user.username, user.role)
                    val newRefreshToken = jwtConfig.generateRefreshToken(user.username)

                    call.respond(
                        HttpStatusCode.OK,
                        ApiResponse(
                            success = true,
                            data = buildJsonObject {
                                put("token", newToken)
                                put("refreshToken", newRefreshToken)
                                put("expiresIn", 3600)
                            },
                            message = "令牌刷新成功"
                        )
                    )
                } else {
                    call.respond(
                        HttpStatusCode.Unauthorized,
                        ApiResponse(
                            success = false,
                            data = null,
                            message = "无效的刷新令牌"
                        )
                    )
                }
            } catch (e: Exception) {
                logger.error(e) { "刷新令牌验证失败: ${e.message}" }
                call.respond(
                    HttpStatusCode.Unauthorized,
                    ApiResponse(
                        success = false,
                        data = null,
                        message = "无效的刷新令牌"
                    )
                )
            }
        } catch (e: Exception) {
            logger.error(e) { "刷新令牌失败: ${e.message}" }
            call.respond(
                HttpStatusCode.InternalServerError,
                ApiResponse(
                    success = false,
                    data = null,
                    message = "刷新令牌失败: ${e.message}"
                )
            )
        }
    }

    // 获取当前用户信息
    authenticate("jwt-auth") {
        get("/me") {
            try {
                val principal = call.principal<JWTPrincipal>()
                val username = principal?.payload?.getClaim("username")?.asString()
                    ?: return@get call.respond(
                        HttpStatusCode.Unauthorized,
                        ApiResponse(
                            success = false,
                            data = null,
                            message = "未授权访问"
                        )
                    )

                val user = repository.findByUsername(username) ?: return@get call.respond(
                    HttpStatusCode.NotFound,
                    ApiResponse(
                        success = false,
                        data = null,
                        message = "用户不存在"
                    )
                )

                call.respond(
                    HttpStatusCode.OK,
                    ApiResponse(
                        success = true,
                        data = buildJsonObject {
                            put("username", user.username)
                            val put: JsonElement? = put("displayName", user.displayName)
                            put("email", user.email)
                            put("role", user.role)
                            put("createdAt", user.createdAt)
                            put("lastLogin", user.lastLoginAt)
                        },
                        message = "获取用户信息成功"
                    )
                )
            } catch (e: Exception) {
                logger.error(e) { "获取当前用户信息失败: ${e.message}" }
                call.respond(
                    HttpStatusCode.InternalServerError,
                    ApiResponse(
                        success = false,
                        data = null,
                        message = "获取当前用户信息失败: ${e.message}"
                    )
                )
            }
        }
    }
}

/**
 * 用户管理 API 路由
 */
fun Route.usersApiRoutes() {
    // 需要用户认证
    authenticate("jwt-auth") {
        // 获取所有用户
        get {
            try {
                val page = call.parameters["page"]?.toIntOrNull() ?: 1
                val pageSize = call.parameters["pageSize"]?.toIntOrNull() ?: 20
                val searchText = call.parameters["searchText"]
                val role = call.parameters["role"]
                val status = call.parameters["status"]

                val users = repository.getAllUsers(page, pageSize)
                val totalCount = repository.getUserCount()
                val totalPages = (totalCount + pageSize - 1) / pageSize

                call.respond(
                    HttpStatusCode.OK,
                    ApiResponse(
                        success = true,
                        data = buildJsonObject {
                            put("users", JsonArray(users.map { user ->
                                buildJsonObject {
                                    put("username", user.username)
                                    put("displayName", user.displayName)
                                    put("email", user.email)
                                    put("role", user.role)
                                    put("status", if (user.enabled) "active" else "inactive")
                                    put("createdAt", user.createdAt)
                                    put("lastLogin", user.lastLoginAt)
                                }
                            }))
                            put("totalCount", totalCount)
                            put("currentPage", page)
                            put("pageSize", pageSize)
                            put("totalPages", totalPages)
                        },
                        message = "获取用户列表成功"
                    )
                )
            } catch (e: Exception) {
                logger.error(e) { "获取用户列表失败: ${e.message}" }
                call.respond(
                    HttpStatusCode.InternalServerError,
                    ApiResponse(
                        success = false,
                        data = null,
                        message = "获取用户列表失败: ${e.message}"
                    )
                )
            }
        }

        // 创建用户
        post {
            try {
                val request = call.receive<CreateUserRequest>()

                // 检查用户名是否已存在
                if (repository.usernameExists(request.username)) {
                    call.respond(
                        HttpStatusCode.Conflict,
                        ApiResponse(
                            success = false,
                            data = null,
                            message = "用户名已存在"
                        )
                    )
                    return@post
                }

                val user = repository.createUser(request)
                call.respond(
                    HttpStatusCode.Created,
                    ApiResponse(
                        success = true,
                        data = buildJsonObject {
                            put("username", user.username)
                            put("displayName", user.displayName)
                            put("email", user.email)
                            put("role", user.role)
                            put("status", if (user.enabled) "active" else "inactive")
                            put("createdAt", user.createdAt)
                            put("lastLogin", user.lastLoginAt)
                        },
                        message = "用户创建成功"
                    )
                )
            } catch (e: Exception) {
                logger.error(e) { "创建用户失败: ${e.message}" }
                call.respond(
                    HttpStatusCode.InternalServerError,
                    ApiResponse(
                        success = false,
                        data = null,
                        message = "创建用户失败: ${e.message}"
                    )
                )
            }
        }

        // 获取单个用户
        get("/{username}") {
            try {
                val username = call.parameters["username"] ?: return@get call.respond(
                    HttpStatusCode.BadRequest,
                    ApiResponse(
                        success = false,
                        data = null,
                        message = "用户名不能为空"
                    )
                )

                val user = repository.findByUsername(username) ?: return@get call.respond(
                    HttpStatusCode.NotFound,
                    ApiResponse(
                        success = false,
                        data = null,
                        message = "用户不存在"
                    )
                )

                call.respond(
                    HttpStatusCode.OK,
                    ApiResponse(
                        success = true,
                        data = buildJsonObject {
                            put("username", user.username)
                            put("displayName", user.displayName)
                            put("email", user.email)
                            put("role", user.role)
                            put("status", if (user.enabled) "active" else "inactive")
                            put("createdAt", user.createdAt)
                            put("lastLogin", user.lastLoginAt)
                        },
                        message = "获取用户成功"
                    )
                )
            } catch (e: Exception) {
                logger.error(e) { "获取用户失败: ${e.message}" }
                call.respond(
                    HttpStatusCode.InternalServerError,
                    ApiResponse(
                        success = false,
                        data = null,
                        message = "获取用户失败: ${e.message}"
                    )
                )
            }
        }

        // 更新用户
        put("/{username}") {
            try {
                val username = call.parameters["username"] ?: return@put call.respond(
                    HttpStatusCode.BadRequest,
                    ApiResponse(
                        success = false,
                        data = null,
                        message = "用户名不能为空"
                    )
                )
                val request = call.receive<UpdateUserRequest>()

                val updatedUser = repository.updateUser(username, request) ?: return@put call.respond(
                    HttpStatusCode.NotFound,
                    ApiResponse(
                        success = false,
                        data = null,
                        message = "用户不存在"
                    )
                )

                call.respond(
                    HttpStatusCode.OK,
                    ApiResponse(
                        success = true,
                        data = buildJsonObject {
                            put("username", updatedUser.username)
                            put("displayName", updatedUser.displayName)
                            put("email", updatedUser.email)
                            put("role", updatedUser.role)
                            put("status", if (updatedUser.enabled) "active" else "inactive")
                            put("createdAt", updatedUser.createdAt)
                            put("lastLogin", updatedUser.lastLoginAt)
                        },
                        message = "用户更新成功"
                    )
                )
            } catch (e: Exception) {
                logger.error(e) { "更新用户失败: ${e.message}" }
                call.respond(
                    HttpStatusCode.InternalServerError,
                    ApiResponse(
                        success = false,
                        data = null,
                        message = "更新用户失败: ${e.message}"
                    )
                )
            }
        }

        // 删除用户
        delete("/{username}") {
            try {
                val username = call.parameters["username"] ?: return@delete call.respond(
                    HttpStatusCode.BadRequest,
                    ApiResponse(
                        success = false,
                        data = null,
                        message = "用户名不能为空"
                    )
                )

                // 不允许删除root用户
                if (username == "root") {
                    call.respond(
                        HttpStatusCode.Forbidden,
                        ApiResponse(
                            success = false,
                            data = null,
                            message = "不能删除管理员账户"
                        )
                    )
                    return@delete
                }

                val deleted = repository.deleteUser(username)

                if (deleted) {
                    call.respond(
                        HttpStatusCode.OK,
                        ApiResponse(
                            success = true,
                            data = null,
                            message = "用户删除成功"
                        )
                    )
                } else {
                    call.respond(
                        HttpStatusCode.NotFound,
                        ApiResponse(
                            success = false,
                            data = null,
                            message = "用户不存在"
                        )
                    )
                }
            } catch (e: Exception) {
                logger.error(e) { "删除用户失败: ${e.message}" }
                call.respond(
                    HttpStatusCode.InternalServerError,
                    ApiResponse(
                        success = false,
                        data = null,
                        message = "删除用户失败: ${e.message}"
                    )
                )
            }
        }

        // 批量删除用户
        post("/bulk-delete") {
            try {
                val request = call.receive<BulkDeleteRequest>()

                // 不允许删除root用户
                if (request.ids.contains("root")) {
                    call.respond(
                        HttpStatusCode.Forbidden,
                        ApiResponse(
                            success = false,
                            data = null,
                            message = "不能删除管理员账户"
                        )
                    )
                    return@post
                }

                // 批量删除用户
                var deletedCount = 0
                request.ids.forEach { id ->
                    if (repository.deleteUser(id)) {
                        deletedCount++
                    }
                }

                call.respond(
                    HttpStatusCode.OK,
                    ApiResponse(
                        success = true,
                        data = buildJsonObject {
                            put("deletedCount", deletedCount)
                        },
                        message = "批量删除用户成功"
                    )
                )
            } catch (e: Exception) {
                logger.error(e) { "批量删除用户失败: ${e.message}" }
                call.respond(
                    HttpStatusCode.InternalServerError,
                    ApiResponse(
                        success = false,
                        data = null,
                        message = "批量删除用户失败: ${e.message}"
                    )
                )
            }
        }

        // 批量更新用户状态
        post("/bulk-update-status") {
            try {
                val request = call.receive<BulkUpdateStatusRequest>()

                // 不允许更新root用户状态
                if (request.ids.contains("root") && request.status != "active") {
                    call.respond(
                        HttpStatusCode.Forbidden,
                        ApiResponse(
                            success = false,
                            data = null,
                            message = "不能禁用管理员账户"
                        )
                    )
                    return@post
                }

                // 批量更新用户状态
                var updatedCount = 0
                request.ids.forEach { id ->
                    val user = repository.findByUsername(id)
                    if (user != null) {
                        val updateRequest = UpdateUserRequest(
                            displayName = user.displayName,
                            email = user.email,
                            role = user.role,
                            enabled = request.status == "active",
                            password = null
                        )
                        if (repository.updateUser(id, updateRequest) != null) {
                            updatedCount++
                        }
                    }
                }

                call.respond(
                    HttpStatusCode.OK,
                    ApiResponse(
                        success = true,
                        data = buildJsonObject {
                            put("updatedCount", updatedCount)
                        },
                        message = "批量更新用户状态成功"
                    )
                )
            } catch (e: Exception) {
                logger.error(e) { "批量更新用户状态失败: ${e.message}" }
                call.respond(
                    HttpStatusCode.InternalServerError,
                    ApiResponse(
                        success = false,
                        data = null,
                        message = "批量更新用户状态失败: ${e.message}"
                    )
                )
            }
        }
    }
} 